#include "precomp.h"
#include "background.h"

Background background;
Background boss_background;

Background::Background()
{
	speed = 1;
	looped = true;
	sprite_num = 0;
	for (int i = 0; i < 200; i++)
		sprite_store[i] = 0;
}

Background::~Background()
{
	unload();
}

void Background::set_speed(float s)
{
	speed = s;
}

void Background::scroll(float time)
{
	// Слои
	for (size_t i = 0; i < layers.size(); i++)
	{
		// Рандомные движения
		if (layers[i].rand_x)
		{
			if (abs(layers[i].rand_current_x - layers[i].rand_next_x) <= layers[i].rand_speed)
				layers[i].rand_next_x = layers[i].rand_x - (layers[i].rand_x * 2 * ((float)(rand()%100) / 100));
			if (layers[i].rand_current_x > layers[i].rand_next_x)
				layers[i].rand_current_x -= layers[i].rand_speed * time;
			else
				layers[i].rand_current_x += layers[i].rand_speed * time;
		}
		if (layers[i].rand_y)
		{
			if (abs(layers[i].rand_current_y - layers[i].rand_next_y) <= layers[i].rand_speed)
				layers[i].rand_next_y = layers[i].rand_y - (layers[i].rand_y * 2 * ((float)(rand()%100) / 100));
			if (layers[i].rand_current_y > layers[i].rand_next_y)
				layers[i].rand_current_y -= layers[i].rand_speed * time;
			else
				layers[i].rand_current_y += layers[i].rand_speed * time;
		}
		// Эффекты изменения в действии
		if (layers[i].action)
		{
			if (layers[i].action == 1)
			{
				// Изменение прозрачности
				layers[i].action_time += time;
				if (layers[i].action_time >= layers[i].action_end_time)
				{
					layers[i].action = 0;
					layers[i].alpha = layers[i].action_result;
				}
				else
				{
					layers[i].alpha += layers[i].action_step * time;
				}
			}
		}
		// Двигаем
		layers[i].current_pos_x += (layers[i].speed_x + layers[i].rand_current_x) * time;
		layers[i].current_pos_y += (layers[i].speed_y * speed + layers[i].rand_current_y) * time; // Вертикальное движение зависит дополнительно от скорости
		if (layers[i].current_pos_x > layers[i].layer_width)
			layers[i].current_pos_x -= layers[i].layer_width;
		if (layers[i].current_pos_x < 0)
			layers[i].current_pos_x += layers[i].layer_width;
		if (layers[i].current_pos_y > layers[i].layer_height)
			layers[i].current_pos_y -= layers[i].layer_height;
		if (layers[i].current_pos_y < 0)
			layers[i].current_pos_y += layers[i].layer_height;
	}
	// Эффекты
	for (size_t i = 0; i < effects.size(); i++)
	{
		// Для каждого эффекта свой обработчик Т_Т
		if (effects[i].effect_type == 0)
			continue;
		else if (effects[i].effect_type == 1)
			continue;
		else if (effects[i].effect_type == 2)
		{
			/* ==================================================
								Падающие листья 
				==================================================
			*/
			effects[i].time_from_last_spawn +=time;
			if (effects[i].time_from_last_spawn >= (speed > 1.0f ? effects[i].spawn_interval/speed : effects[i].spawn_interval))
			{
				// Новый лист
				if (effects[i].num_particles < effects[i].max_particles)
				{
					effects[i].time_from_last_spawn -= effects[i].spawn_interval;
					Effect_Particle temp_particle;
					// Стартовая позиция с захлёстом за экран
					temp_particle.position = CL_Vec2<float>(float(rand()%(100 + visible_rect.right - visible_rect.left)+visible_rect.left - 50), (float)(rand()%(200 + visible_rect.bottom - visible_rect.top) - 200) * effects[i].spawn_field + visible_rect.top);
					// Двигаем на падение вниз
					CL_Angle t_angle;
					t_angle.set_degrees(30 + rand()%120);
					float t_speed = effects[i].speed_min + (effects[i].speed_max - effects[i].speed_min) * ((float)(rand()%100) / 100);
					temp_particle.move = CL_Vec2<float>(t_speed * cos(t_angle.to_radians()), t_speed * sin(t_angle.to_radians()));
					temp_particle.angle.set_degrees(rand()%360);
					temp_particle.color = effects[i].color;
					// рандомно подкручивать цвета
					//temp_particle.color.set_green(temp_particle.color.get_green() + (effects[i].color.get_green() * (rand()%50 - 25)) / 50);
					//temp_particle.color.set_blue(temp_particle.color.get_blue() + (effects[i].color.get_blue() * (rand()%50 - 25)) / 50);
					//temp_particle.color.set_red(temp_particle.color.get_red() + (effects[i].color.get_red() * (rand()%50 - 25)) / 50);
					temp_particle.lifespan = effects[i].life_min + rand()%(int)(effects[i].life_max - effects[i].life_min);
					temp_particle.lived = 0;
					temp_particle.rotation_speed = effects[i].rotation_min + (effects[i].rotation_max - effects[i].rotation_min) * ((float)(rand()%100) / 100);
					if (rand()%2 == 0)
						temp_particle.rotation_speed = -temp_particle.rotation_speed;
					temp_particle.size = effects[i].size_min + (effects[i].size_max - effects[i].size_min) * ((float)(rand()%100) / 100);;
					temp_particle.fade = 0;

					effects[i].effect_particles.push_back(temp_particle);
				}
			}
			// Двигаем имеющиеся
			size_t c = 0;
			while ( c < effects[i].effect_particles.size())
			{
				effects[i].effect_particles[c].lived += time;
				if (effects[i].effect_particles[c].lived > effects[i].effect_particles[c].lifespan)
					effects[i].effect_particles.erase(effects[i].effect_particles.begin() + c);
				else
					c++;
			}
			for (c = 0; c < effects[i].effect_particles.size(); c++)
			{
				effects[i].effect_particles[c].position.y += effects[i].scroll_speed * time * speed; // вертикальный общий скроллинг, зависит от скорости
				effects[i].effect_particles[c].position += effects[i].effect_particles[c].move * time;
				effects[i].effect_particles[c].angle.set_degrees(effects[i].effect_particles[c].angle.normalize().to_degrees() + effects[i].effect_particles[c].rotation_speed * time);
				if (effects[i].effect_particles[c].lived < effects[i].fade)
					effects[i].effect_particles[c].fade = effects[i].effect_particles[c].lived / effects[i].fade;
				if (effects[i].effect_particles[c].fade > 1)
					effects[i].effect_particles[c].fade = 1;
				if (effects[i].effect_particles[c].lived > (effects[i].effect_particles[c].lifespan - effects[i].fade))
					effects[i].effect_particles[c].fade = (effects[i].effect_particles[c].lifespan - effects[i].effect_particles[c].lived) / effects[i].fade;
			}
		}
		else if (effects[i].effect_type == 3)
		{
			/* ==================================================
								Облака
				==================================================
			*/
			effects[i].time_from_last_spawn +=time;
			if (effects[i].time_from_last_spawn >= effects[i].time_to_next_spawn)
			{
				// Новое облако
				if (effects[i].num_particles < effects[i].max_particles)
				{
					effects[i].time_from_last_spawn -= effects[i].time_to_next_spawn;
					effects[i].time_to_next_spawn = (effects[i].spawn_interval / 2 + (effects[i].spawn_interval / 2) * ((float)(rand()%100) / 100)) / speed;
					Effect_Particle temp_particle;
					// Стартовая позиция за экраном
					temp_particle.position = CL_Vec2<float>(rand()%(100 + visible_rect.right - visible_rect.left)+visible_rect.left - 50, -65.0f * effects[i].zoom);
					// Небольшой угол при движении
					CL_Angle t_angle;
					t_angle.set_degrees(85 + rand()%10);
					temp_particle.move = CL_Vec2<float>(layers[(int)effects[i].follow_layer].speed_y * effects[i].speed * cos(t_angle.to_radians()), layers[(int)effects[i].follow_layer].speed_y * effects[i].speed * sin(t_angle.to_radians()));
					// Частота смены фаз анимации
					temp_particle.lived = 0;
					temp_particle.lifespan = 500;
					temp_particle.size = effects[i].size_min + (effects[i].size_max - effects[i].size_min) * ((float)(rand()%100) / 100);;
					// Вид облака
					temp_particle.p_type = rand()%2;
					temp_particle.anim = 0;
					temp_particle.current_zoom = 1;

					effects[i].effect_particles.push_back(temp_particle);
				}
			}
			// Двигаем имеющиеся
			size_t c = 0;
			while ( c < effects[i].effect_particles.size())
			{
				if (effects[i].effect_particles[c].position.y > visible_rect.bottom + 65.0f * effects[i].effect_particles[c].current_zoom)
					effects[i].effect_particles.erase(effects[i].effect_particles.begin() + c);
				else
					c++;
			}
			for (c = 0; c < effects[i].effect_particles.size(); c++)
			{
				// Анимация
				effects[i].effect_particles[c].lived += time;
				if (effects[i].effect_particles[c].lived > effects[i].effect_particles[c].lifespan)
				{
					effects[i].effect_particles[c].lived -= effects[i].effect_particles[c].lifespan;
					if (effects[i].effect_particles[c].anim == 0)
						effects[i].effect_particles[c].anim = 1;
					else
						effects[i].effect_particles[c].anim = 0;
				}
				// Движение параллельно слою фона
				float layer_speed_x = layers[(int)effects[i].follow_layer].rand_current_x;
				float layer_speed_y = layers[(int)effects[i].follow_layer].rand_current_y;

				effects[i].effect_particles[c].position.y += (effects[i].effect_particles[c].move.y + layer_speed_y) * effects[i].effect_particles[c].current_zoom * time * speed; // вертикальный общий скроллинг, зависит от скорости
				effects[i].effect_particles[c].position.x += (effects[i].effect_particles[c].move.x + layer_speed_x) * time;
				// Увеличение при движении вперёд
				if (effects[i].effect_particles[c].position.y > -128 * effects[i].effect_particles[c].size)
					effects[i].effect_particles[c].current_zoom = 1 + ((effects[i].effect_particles[c].position.y + 128) / (visible_rect.bottom + 128)) * (effects[i].zoom - 1);
			}
		}
		else if (effects[i].effect_type == 4)
		{
			/* ==================================================
								Деревья
				==================================================
			*/
			effects[i].time_from_last_spawn +=time;
			if (effects[i].time_from_last_spawn >= effects[i].spawn_interval / speed)
			{
				effects[i].time_from_last_spawn -= effects[i].spawn_interval / speed;
				// Новый ряд  деревьев
				if (effects[i].fill_left || effects[i].fill_right || effects[i].fill_center)
				{
					int trees_left = 0;
					int trees_right = 0;
					int trees_center = 0;
					// Распределим деревья по полосам
					int r = 0;
					while ( r < effects[i].max_particles )
					{
						int where_to_go = rand()%3;
						if (where_to_go == 0 && effects[i].fill_left)
						{
							trees_left++;
							r++;
						}
						if (where_to_go == 1 && effects[i].fill_right)
						{
							trees_right++;
							r++;
						}
						if (where_to_go == 2 && effects[i].fill_center)
						{
							trees_center++;
							r++;
						}
					}
					// Рассадим новые деревья
					while (trees_left)
					{
						Effect_Particle temp_particle;
						// Стартовая позиция за экраном
						float start_pos = global_state.render_field.left;
						float polosa = global_state.render_field.get_width() / 3.0f;
						temp_particle.position = CL_Vec2f(start_pos + rand()%(int)polosa, -65.0f * effects[i].size_max);
						temp_particle.move = CL_Vec2f(0, 1.0f);
						if (trees_left < 2 && polosa > 130.0f)
						{
							// Подкрутить позицию, чтобы деревья не шли слишком близко друг к другу
							while (abs(temp_particle.position.x - effects[i].last_left) < 64.0f)
								temp_particle.position.x = start_pos + rand()%(int)polosa;
						}
						// Параметры
						temp_particle.lived = 0;
						temp_particle.size = effects[i].size_min + (effects[i].size_max - effects[i].size_min) * ((float)(rand()%100) / 100);;
						// Вид дерева
						temp_particle.p_type = rand()%2;

						effects[i].effect_particles.push_back(temp_particle);
						trees_left--;
					}
					while (trees_center)
					{
						Effect_Particle temp_particle;
						// Стартовая позиция за экраном
						float polosa = global_state.render_field.get_width() / 3.0f;
						float start_pos = global_state.render_field.left + polosa;
						temp_particle.position = CL_Vec2f(start_pos + rand()%(int)polosa, -65.0f * effects[i].size_max);
						temp_particle.move = CL_Vec2f(0, 1.0f);
						if (trees_center < 2 && polosa > 130.0f)
						{
							// Подкрутить позицию, чтобы деревья не шли слишком близко друг к другу
							while (abs(temp_particle.position.x - effects[i].last_center) < 64.0f)
								temp_particle.position.x = start_pos + rand()%(int)polosa;
						}
						// Параметры
						temp_particle.lived = 0;
						temp_particle.size = effects[i].size_min + (effects[i].size_max - effects[i].size_min) * ((float)(rand()%100) / 100);;
						// Вид дерева
						temp_particle.p_type = rand()%2;

						effects[i].effect_particles.push_back(temp_particle);
						trees_center--;
					}
					while (trees_right)
					{
						Effect_Particle temp_particle;
						// Стартовая позиция за экраном
						float polosa = global_state.render_field.get_width() / 3.0f;
						float start_pos = global_state.render_field.left + polosa*2.0f;
						temp_particle.position = CL_Vec2f(start_pos + rand()%(int)polosa, -65.0f * effects[i].size_max);
						temp_particle.move = CL_Vec2f(0, 1.0f);
						if (trees_right < 2 && polosa > 130.0f)
						{
							// Подкрутить позицию, чтобы деревья не шли слишком близко друг к другу
							while (abs(temp_particle.position.x - effects[i].last_right) < 64.0f)
								temp_particle.position.x = start_pos + rand()%(int)polosa;
						}
						// Параметры
						temp_particle.lived = 0;
						temp_particle.size = effects[i].size_min + (effects[i].size_max - effects[i].size_min) * ((float)(rand()%100) / 100);;
						// Вид дерева
						temp_particle.p_type = rand()%2;

						effects[i].effect_particles.push_back(temp_particle);
						trees_right--;
					}
				}
			}
			// Двигаем имеющиеся
			size_t c = 0;
			while ( c < effects[i].effect_particles.size())
			{
				if (effects[i].effect_particles[c].position.y > visible_rect.bottom + 64)
					effects[i].effect_particles.erase(effects[i].effect_particles.begin() + c);
				else
					c++;
			}
			for (c = 0; c < effects[i].effect_particles.size(); c++)
			{
				effects[i].effect_particles[c].lived += time;
				// Движение параллельно слою фона
				float layer_speed_x = layers[(int)effects[i].follow_layer].rand_current_x + layers[(int)effects[i].follow_layer].speed_x;
				float layer_speed_y = layers[(int)effects[i].follow_layer].rand_current_y + layers[(int)effects[i].follow_layer].speed_y + effects[i].speed;

				effects[i].effect_particles[c].position.y += effects[i].effect_particles[c].move.y * layer_speed_y * time * speed; // вертикальный общий скроллинг, зависит от скорости
				effects[i].effect_particles[c].position.x += effects[i].effect_particles[c].move.x * layer_speed_x * time;
			}
		}
		// ====================================================
	}
}

void Background::load(CL_GraphicContext &gc, const CL_String &level, CL_ResourceManager &resources, CL_Rect v_rect)
{
	// Освободим загруженные ранее ресурсы
	unload();

	//visible_rect = (CL_Rect) global_state.render_field;
	visible_rect = v_rect;
	origin_x = visible_rect.left-10;
	origin_y = visible_rect.top-10;

	// Получим корень дерева ресурса уровня
	CL_Resource resource = resources.get_resource(level);
	CL_DomElement element = resource.get_element();
	background_color = CL_Colorf(element.get_attribute("background_color"));

	if (element.has_attribute("clear"))
		clear_flag = CL_StringHelp::text_to_int(element.get_attribute("clear"));
	else
		clear_flag = 1;

	// Параметры перспективы
	CL_DomNode perspective_node = element.named_item("perspective");
	if (!perspective_node.is_null())
	{
		perspective = true;
		std::map<std::string, CL_String> perspective_params;
		std::vector<CL_DomNode> perspective_params_nodes = perspective_node.to_element().select_nodes("param");
		for (size_t p_index = 0; p_index < perspective_params_nodes.size(); p_index++)
			perspective_params[perspective_params_nodes[p_index].to_element().get_attribute("name").c_str()] = perspective_params_nodes[p_index].to_element().get_text();
		lens_zoom = CL_StringHelp::text_to_float(perspective_params["lens_zoom"]);
		lens_near = CL_StringHelp::text_to_float(perspective_params["lens_near"]);
		lens_far = CL_StringHelp::text_to_float(perspective_params["lens_far"]);
		lens_aspect = CL_StringHelp::text_to_float(perspective_params["lens_aspect"]);
		perspective_angle = CL_Angle(CL_StringHelp::text_to_float(perspective_params["angle"]), cl_degrees);
		fov = 2.0f * atan2(1.0f, lens_zoom);
		float aspect = 1.0f;
		aspect = ( (float)visible_rect.get_width() * lens_aspect) / (float)visible_rect.get_height();
		fov = (fov * 180.0f) / CL_PI;
		projection_matrix = CL_Mat4f::perspective( fov, aspect, lens_near, lens_far);
		modelview_matrix = CL_Mat4f::identity();
		modelview_matrix.scale_self(1.0f, 1.0f, -1.0f);	// So positive Z goes into the screen
		modelview_matrix.translate_self(-1.0f, 1.0, lens_zoom);
		modelview_matrix = modelview_matrix.multiply(CL_Mat4f::rotate(perspective_angle, 1.0f, 0.0f, 0.0f, false));
		modelview_matrix.scale_self(2.0f / (float)visible_rect.get_width(), -2.0f / (float)visible_rect.get_height(), 1.0f);
		modelview_matrix.translate_self(cl_pixelcenter_constant,cl_pixelcenter_constant, 0.0f);
	}
	else
		perspective = false;

	// Загрузим все слои
	std::vector<CL_DomNode> layer_nodes = element.select_nodes("layer");
	for (size_t layer_index = 0; layer_index < layer_nodes.size(); layer_index++)
	{
		CL_DomElement layer_element = layer_nodes[layer_index].to_element();
		Layer temp_layer;

		temp_layer.name = layer_element.get_attribute("name");
		temp_layer.current_pos_x = 0;
		temp_layer.current_pos_y = 0;
		temp_layer.rand_next_x = 0;
		temp_layer.rand_next_y = 0;
		temp_layer.rand_current_x = 0;
		temp_layer.rand_current_y = 0;
		temp_layer.action = 0;

		// Параметры
		std::map<std::string, CL_String> params;
		std::vector<CL_DomNode> param_nodes = layer_element.select_nodes("param");
		for (size_t p_index = 0; p_index < param_nodes.size(); p_index++)
			params[param_nodes[p_index].to_element().get_attribute("name").c_str()] = param_nodes[p_index].to_element().get_text();
		temp_layer.speed_x = CL_StringHelp::text_to_float(params["speed_x"]);
		temp_layer.speed_y = CL_StringHelp::text_to_float(params["speed_y"]);
		temp_layer.zoom_x = CL_StringHelp::text_to_float(params["zoom_x"]);
		temp_layer.zoom_y = CL_StringHelp::text_to_float(params["zoom_y"]);
		if (params.find("alpha") != params.end())
			temp_layer.alpha = CL_StringHelp::text_to_float(params["alpha"]);
		else
			temp_layer.alpha = 1.0f;
		// Необязательные параметры
		if (params.find("offset_x") == params.end())
		{
			temp_layer.offset_x = 0;
			temp_layer.offset_y = 0;
		}
		else
		{
			temp_layer.offset_x = CL_StringHelp::text_to_float(params["offset_x"]);
			temp_layer.offset_y = CL_StringHelp::text_to_float(params["offset_y"]);
		}
		if (params.find("rand_x") == params.end())
			temp_layer.rand_x = 0;
		else
			temp_layer.rand_x = CL_StringHelp::text_to_float(params["rand_x"]);
		if (params.find("rand_y") == params.end())
			temp_layer.rand_y = 0;
		else
			temp_layer.rand_y = CL_StringHelp::text_to_float(params["rand_y"]);
		if (params.find("rand_speed") == params.end())
			temp_layer.rand_speed = 0;
		else
			temp_layer.rand_speed = CL_StringHelp::text_to_float(params["rand_speed"]);

		// Карта
		CL_DomElement tilemap = layer_element.select_node("tilemap").to_element();
		temp_layer.sprite = tilemap.get_attribute("resource");
		temp_layer.map_width = tilemap.get_attribute_int("width");
		temp_layer.map_height = tilemap.get_attribute_int("height");

		CL_String layer_tiles = tilemap.get_text();
		std::vector<CL_String> tile_indices = CL_StringHelp::split_text(layer_tiles, ",");
		temp_layer.map.reserve(tile_indices.size());
		for(size_t i = 0; i < tile_indices.size(); ++i)
			temp_layer.map.push_back(CL_StringHelp::text_to_int(tile_indices[i]));

		// Теперь загрузим спрайт для этого слоя
		sprite_store[sprite_num] = new CL_Sprite(gc, temp_layer.sprite, &resources);
		temp_layer._sprite = sprite_store[sprite_num];
		sprite_num++;
		temp_layer.tile_width = temp_layer._sprite->get_width();
		temp_layer.tile_height = temp_layer._sprite->get_height();
		temp_layer.layer_width = temp_layer.map_width * temp_layer.tile_width;
		temp_layer.layer_height = temp_layer.map_height * temp_layer.tile_height;

		// Установим стартовую позицию самого нижнего тайла на нижнюю границу экрана
		temp_layer.current_pos_y = (visible_rect.bottom - visible_rect.top) - (temp_layer.map_height * temp_layer.tile_height);

		layers.push_back(temp_layer);
	}

	// Загрузим все эффекты
	std::vector<CL_DomNode> effect_nodes = element.select_nodes("effect");
	for (size_t effect_index = 0; effect_index < effect_nodes.size(); effect_index++)
	{
		CL_DomElement effect_element = effect_nodes[effect_index].to_element();
		BG_Effect temp_effect;

		temp_effect.name = effect_element.get_attribute("name");
		// Определим что за это эффект
		if (temp_effect.name == "happa")
			temp_effect.effect_type = 2;
		else if (temp_effect.name == "clouds")
			temp_effect.effect_type = 3;
		else if (temp_effect.name == "trees")
			temp_effect.effect_type = 4;
		else
			continue;

		// Параметры
		temp_effect.time_from_last_spawn = 0;
		temp_effect.time_to_next_spawn = 10;
		temp_effect.num_particles = 0;

		std::map<std::string, CL_String> params;
		std::vector<CL_DomNode> param_nodes = effect_element.select_nodes("param");
		for (size_t p_index = 0; p_index < param_nodes.size(); p_index++)
			params[param_nodes[p_index].to_element().get_attribute("name").c_str()] = param_nodes[p_index].to_element().get_text();

		// количество частиц
		temp_effect.max_particles = CL_StringHelp::text_to_float(params["number"]);
		// Скорость движения
		if (params.find("speed_min") != params.end())
			temp_effect.speed_min = CL_StringHelp::text_to_float(params["speed_min"]);
		if (params.find("speed") != params.end())
			temp_effect.speed = CL_StringHelp::text_to_float(params["speed"]);
		if (params.find("speed_max") != params.end())
			temp_effect.speed_max = CL_StringHelp::text_to_float(params["speed_max"]);
		// Скорость общего подскролливания эффекта
		if (params.find("scroll_speed") != params.end())
			temp_effect.scroll_speed = CL_StringHelp::text_to_float(params["scroll_speed"]);
		// Скорость вращения
		if (params.find("rotation_min") != params.end())
			temp_effect.rotation_min = CL_StringHelp::text_to_float(params["rotation_min"]);
		if (params.find("rotation_max") != params.end())
			temp_effect.rotation_max = CL_StringHelp::text_to_float(params["rotation_max"]);
		// Время жизни
		if (params.find("life_min") != params.end())
			temp_effect.life_min = CL_StringHelp::text_to_float(params["life_min"]);
		if (params.find("life_max") != params.end())
			temp_effect.life_max = CL_StringHelp::text_to_float(params["life_max"]);
		// Время появления на экране и угасания ->   |_fade_|______live________|_fade_|
		if (params.find("fade") != params.end())
			temp_effect.fade = CL_StringHelp::text_to_float(params["fade"]);
		// Размеры частицы
		if (params.find("size_min") != params.end())
			temp_effect.size_min = CL_StringHelp::text_to_float(params["size_min"]);
		if (params.find("size_max") != params.end())
			temp_effect.size_max = CL_StringHelp::text_to_float(params["size_max"]);
		// Относительное увеличение при движении через экран
		if (params.find("zoom") != params.end())
			temp_effect.zoom = CL_StringHelp::text_to_float(params["zoom"]);
		// Вертикальный размер зоны появления
		if (params.find("spawn_field") != params.end())
			temp_effect.spawn_field = CL_StringHelp::text_to_float(params["spawn_field"]);
		// Интервал появления
		if (params.find("spawn_time") != params.end())
			temp_effect.spawn_interval = CL_StringHelp::text_to_float(params["spawn_time"]);
		// Цвет(в хекс-формате) и альфа-канал
		if (params.find("color") != params.end())
			temp_effect.color = CL_Color(params["color"]);
		else
			temp_effect.color = CL_Color(255,255,255);
		if (params.find("alpha") != params.end())
			temp_effect.alpha = CL_StringHelp::text_to_float(params["alpha"]);
		else
			temp_effect.alpha = 1.0f;
		if (params.find("rand_color") != params.end())
			temp_effect.rand_color = CL_Color(params["rand_color"]);
		else
			temp_effect.rand_color = CL_Color(0,0,0);
		// Индекс в спрайте
		if (params.find("index") != params.end())
			temp_effect.effect_index = CL_StringHelp::text_to_int(params["index"]);
		else
			temp_effect.effect_index = 0;
		// Название слоя, параллельно которому следует эффект
		if (params.find("follow_layer") != params.end())
			for (size_t layer_to_find=0; layer_to_find < layers.size(); layer_to_find++)
				if (layers[layer_to_find].name == params["follow_layer"])
					temp_effect.follow_layer = layer_to_find;
		// Параметры для эффекта деревьев:
		// зоны заполнения
		if (params.find("fill_left") != params.end())
			temp_effect.fill_left = CL_StringHelp::text_to_int(params["fill_left"]);
		if (params.find("fill_right") != params.end())
			temp_effect.fill_right = CL_StringHelp::text_to_int(params["fill_right"]);
		if (params.find("fill_center") != params.end())
			temp_effect.fill_center = CL_StringHelp::text_to_int(params["fill_center"]);
		temp_effect.last_left = 0;
		temp_effect.last_right = 0;
		temp_effect.last_center = 0;

		// Теперь загрузим спрайт для этого слоя
		if (temp_effect.effect_type == 2)
		{
			temp_effect._sprite = sprite_container.GetSprite("effects");
		}
		else
		{
			temp_effect.sprite = effect_element.get_attribute("resource");
			sprite_store[sprite_num] = new CL_Sprite(gc, temp_effect.sprite, &resources);
			temp_effect._sprite = sprite_store[sprite_num];
			sprite_num++;
		}

		effects.push_back(temp_effect);
	}
	
}

void Background::draw(CL_GraphicContext &gc)
{
	// Область вывода
	gc.set_cliprect(global_state.bg_rect);
	if (clear_flag)
		gc.clear(background_color);
	// Сначала рисуем слои один за другим
	// Если задано - с перспективой
	//if (perspective)
	//{
	//	gc.set_map_mode(CL_MapMode::cl_user_projection);
	//	gc.set_viewport(global_state.clip_rect);
	//	gc.set_projection(projection_matrix);
	//	gc.set_modelview(modelview_matrix);
	//}
	for (size_t i = 0; i < layers.size(); i++)
	{
		// зум
		//if (perspective)
		//{
		//	gc.push_modelview();
		//	gc.set_modelview(modelview_matrix);
		//	gc.mult_modelview(CL_Mat4f::scale(layers[i].zoom_x, layers[i].zoom_y, 1.0));
		//}
		//else
		{
			gc.push_modelview();
			gc.mult_scale(layers[i].zoom_x, layers[i].zoom_y);
		}
		int dx,dy;
		for (dy = -layers[i].map_height; dy < layers[i].map_height; dy++)
		{
			for (dx = -layers[i].map_width; dx < layers[i].map_width; dx++)
			{
				// Позиция текущего тайла
				CL_Rectf p(origin_x + dx * layers[i].tile_width + layers[i].current_pos_x + layers[i].offset_x, origin_y + dy * layers[i].tile_height + layers[i].current_pos_y + layers[i].offset_y, origin_x + dx * layers[i].tile_width + layers[i].current_pos_x + layers[i].tile_width + layers[i].offset_x, origin_y + dy * layers[i].tile_height + layers[i].current_pos_y + layers[i].tile_height + layers[i].offset_y);
				// Попадает ли на экран
				if (visible_rect.is_overlapped(p))
				{
					int cx = dx;
					int cy = dy;
					if (cx < 0)
						cx += layers[i].map_width;
					if (cy < 0)
						cy += layers[i].map_height;
					int sprite_index = layers[i].map[(cy * layers[i].map_width) + cx];
					layers[i]._sprite->set_frame(sprite_index);
					layers[i]._sprite->set_alpha(layers[i].alpha);
					layers[i]._sprite->draw(gc, p);
				}
			}
		}
		gc.pop_modelview();
	}
	//if (perspective)
	//{
	//	gc.pop_modelview();
	//	gc.set_map_mode(CL_MapMode::cl_map_2d_upper_left);
	//}

	// Теперь поверх всего - эффекты
	for (size_t i = 0; i < effects.size(); i++)
	{
		// Для каждого типа свой рендерер Т_Т
		if (effects[i].effect_type == 0)
			continue;
		else if (effects[i].effect_type == 1)
			continue;
		else if (effects[i].effect_type == 2)
		{
			/* ==================================================
								Падающие листья и другие частицы
				==================================================
			*/
			effects[i]._sprite->set_frame(effects[i].effect_index);
			std::vector<Effect_Particle>::iterator h;
			for(h = effects[i].effect_particles.begin(); h < effects[i].effect_particles.end(); h++)
			{
				effects[i]._sprite->set_color(h->color);
				effects[i]._sprite->set_scale(h->size, h->size);
				effects[i]._sprite->set_angle(h->angle);
				effects[i]._sprite->set_alpha(effects[i].alpha * h->fade);
				effects[i]._sprite->set_alignment(origin_center);
				effects[i]._sprite->draw(gc, h->position.x, h->position.y);
				effects[i]._sprite->set_color(CL_Colorf::white);
				effects[i]._sprite->set_scale(1.0f, 1.0f);
				effects[i]._sprite->set_alpha(1.0f);
			}
		}
		else if (effects[i].effect_type == 3)
		{
			/* ==================================================
								Облака
				==================================================
			*/
			std::vector<Effect_Particle>::iterator h;
			for(h = effects[i].effect_particles.begin(); h < effects[i].effect_particles.end(); h++)
			{
				float s_size = h->size * h->current_zoom;
				effects[i]._sprite->set_frame(h->p_type * 2);
				effects[i]._sprite->set_scale(s_size, s_size);
				effects[i]._sprite->set_alpha(effects[i].alpha);
				effects[i]._sprite->set_alignment(origin_center);
				effects[i]._sprite->draw(gc, h->position.x, h->position.y);
			}
		}
		else if (effects[i].effect_type == 4)
		{
			/* ==================================================
								Деревья
				==================================================
			*/
			std::vector<Effect_Particle>::iterator h;
			for(h = effects[i].effect_particles.begin(); h < effects[i].effect_particles.end(); h++)
			{
				effects[i]._sprite->set_frame(h->p_type + 1);
				effects[i]._sprite->set_scale(h->size, h->size);
				effects[i]._sprite->set_alpha(effects[i].alpha);
				effects[i]._sprite->set_alignment(origin_center);
				effects[i]._sprite->draw(gc, h->position.x, h->position.y);
			}
		}
	}

	// Убрать область вывода
	gc.pop_cliprect();
}

// Сдувать снежинки бомбой Аечки
void Background::bomb_blow()
{
	for (size_t i = 0; i < effects.size(); i++)
	{
		if (effects[i].effect_type == 2)
		{
			for (size_t c = 0; c < effects[i].effect_particles.size(); c++)
			{
				effects[i].effect_particles[c].move = CL_Vec2f(0, -1.0f);
			}
		}
	}
}

// Сдувать снежинки ветром
void Background::player_blow()
{
	for (size_t i = 0; i < effects.size(); i++)
	{
		if (effects[i].effect_type == 2)
		{
			for (size_t c = 0; c < effects[i].effect_particles.size(); c++)
			{
				if (player.position.distance(effects[i].effect_particles[c].position) < player.wind_current_radius)
					effects[i].effect_particles[c].move = (effects[i].effect_particles[c].position - player.position).normalize();
			}
		}
	}
}

// Сменить прозрачность слоя за промежуток времени
void Background::change_layer_alpha(CL_String layer_name, float target_alpha, float timing)
{
	int layer_n = -1;
	for (size_t i = 0; i < layers.size(); i++)
		if (layers[i].name == layer_name)
			layer_n = i;
	if (layer_n >=0)
	{
		layers[layer_n].action = 1; // смена прозрачности
		layers[layer_n].action_time = 0;
		layers[layer_n].action_end_time = timing;
		layers[layer_n].action_result = target_alpha;
		layers[layer_n].action_step = (target_alpha - layers[layer_n].alpha) / timing;
	}
}

void Background::show_layer(CL_String layer_name, float timing)
{
	change_layer_alpha(layer_name, 1.0f, timing);
}

void Background::hide_layer(CL_String layer_name, float timing)
{
	change_layer_alpha(layer_name, 0, timing);
}

void Background::unload()
{
	layers.clear();
	effects.clear();
	for (int i = 0; i < sprite_num; i ++)
	{
		delete sprite_store[i];
		sprite_store[i] = 0;
	}
	sprite_num = 0;
}
